<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>cart</title>
  <script src="/vue.js"></script>
</head>
<body>
  <div id="root">
    <table border="1" style="width: 100%">
      <tbody>
        <tr>
          <th style="width: 70px;">
            <input 
              type="checkbox"
              :checked="checkedValue"
              @change="handleChange"
            /> 全选</th>
          <th>商品信息</th>
          <th>商品参数</th>
          <th>单价</th>
          <th style="width: 120px;">数量</th>
          <th>金额</th>
          <th>操作</th>
        </tr>
      </tbody>
      <tbody
        is="c-shop"
        v-for="shop,key,index in datasource"
        :shop-name="key"
        :shop="shop"
        :key="key"
        :all-checked="allChecked"
        :index="index"
        @on-checked="handleChecked"
        @on-shop-checked="handleShopChecked"
        @on-change-quantity="handleChangeQuantity"
        :item-key="key"
      ></tbody>
    </table>
    <div>{{totalPrice}}</div>
  </div>

  <script>
    Vue.component('c-item', {
      props: {
        item: Object,
        checkValue: Boolean,
        itemIndex: Number,
        shopIndex: Number,
        allChecked: Array,
        itemKey: String
      },

      data() {
        return {
          newItem: {
            ...this.item,
            quantity: 0
          }
        }
      },

      template: `
        <tr>
          <td>
            <input 
              type="checkbox"
              :checked="allChecked[shopIndex][itemIndex]"
              @change="handleChange"
            />
          </td>
          <td>{{newItem.info}}</td>
          <td>{{newItem.paramaters}}</td>
          <td>￥{{newItem.price}}</td>
          <td>
            <button
              @click="decrement(newItem.price)"
              :disabled="newItem.quantity <= 0"
            >-</button>
            <input type="text" 
              v-model="newItem.quantity" 
              style="width:40px;"
            />
            <button 
              :disabled="newItem.quantity > newItem.inventory" 
              @click="increment(newItem.price)"
            >+</button>
          </td>
          <td>￥ {{totalPrice}}</td>
          <td>
            <button @click="handleRemove">移除</button>
          </td>
        </tr>
      `,

      created() {
        
      },

      computed: {
        totalPrice() {
          return this.newItem.price * this.newItem.quantity
        }
      },
    
      methods: {
        emitQuantity(price) {
          if (this.allChecked[this.shopIndex][this.itemIndex]) {
            this.$emit('on-change-quantity', price)
          }
        },
        increment(price) {
          let {quantity, inventory} = this.newItem
          if (quantity <= inventory) {
            this.newItem.quantity++
          }
          this.emitQuantity(price)
        },
        decrement(price) {
          let {quantity} = this.newItem
          if (quantity > 0) {
            this.newItem.quantity--
          }
          this.emitQuantity(-price)
        },
        handleChange(e) {
          let value = e.target.checked
          this.$emit('on-checked', {
            value,
            shopIndex: this.shopIndex,
            itemIndex: this.itemIndex
          })

          let newPrice = this.allChecked[this.shopIndex][this.itemIndex] 
            ? this.totalPrice 
            : -this.totalPrice

          this.$emit('on-change-quantity', newPrice)
        },

        handleRemove() {
          let newPrice = this.allChecked[this.shopIndex][this.itemIndex] 
            ? this.totalPrice 
            : -this.totalPrice

          this.$root.removeProduct(this.itemKey, this.itemIndex, newPrice)
        }
      },
    
      watch: {
        checkValue(value) {
          // console.log(this.allChecked)
          // this.newItem.isChecked = value
        }
      }
    })

    Vue.component('c-shop', {
      props: {
        shop: Array,
        shopName: String,
        allChecked: Array,
        index: Number,
        itemKey: String
      },

      data() {
        return {
          // checkValue: false
        }
      },

      template: `
        <tbody>
          <tr width="100%">
            <td colspan="7">
              <input 
                type="checkbox"
                :checked="checkValue"
                @change="handleSelectAll"
              />店铺：{{shopName}}
            </td>
          </tr>
          <tr 
            is="c-item"
            v-for="item,i in shop"
            :item="item"
            :key="item.id"
            @on-checked="handleChecked"
            @on-change-quantity="handleChangeQuantity"
            :all-checked="allChecked"
            :item-index="i"
            :shop-index="index"
            :item-key="itemKey"
          ></tr>
        </tbody>
      `,

      methods: {
        handleChecked(checked) {
          this.$emit('on-checked', checked)
        },

        initAllChecked() {
          return {
            allTrue: this.shop.map((value) => true),
            allFalse: this.shop.map((value) => false)
          }
        },

        handleSelectAll(e) {
          this.$emit('on-shop-checked', {
            value: e.target.checked,
            shopIndex: this.index
          })
        },

        handleChangeQuantity(price) {
          this.$emit('on-change-quantity', price)
        },

      },

      computed: {
        checkValue() {
          return this.allChecked[this.index].every(v => v)
        }
      },

      created() {
        // let { allFalse } = this.initAllChecked()
        // this.allChecked = allFalse
      },

      watch: {
        // allChecked(value) {
        //   let result = value.every(v => v)
        //   this.checkValue = result
        // },
        // checkValue(value) {
        //   if (!value) {
        //     this.allChecked = this.shop.map((value) => false)
        //   } else {
        //     this.allChecked = this.shop.map((value) => true)
        //   }
        // }
      }
    })

    var vm = new Vue({
      el: '#root',
      data: {
        datasource: {},
        allChecked: [],
        totalPrice: 0
      },

      computed: {
        checkedValue() {
          return this.allChecked.flat().every(v => v)
        }
      },
      
      methods: {
        initAllChecked() {
          let keys = Object.keys(this.datasource)

          let allFalse = keys.map(value => {
            return this.datasource[value].map(value2 => false)
          })

          let allTrue = keys.map(value => {
            return this.datasource[value].map(value2 => true)
          })

          return {
            allTrue,
            allFalse
          }
        },

        handleChangeQuantity(price) {
          this.totalPrice += price
        },

        handleChange(e) {
          let { allTrue, allFalse } = this.initAllChecked()
          let value = e.target.checked
          this.checkValue = value
          this.allChecked = value ? allTrue : allFalse
        },

        handleChecked({value, itemIndex, shopIndex}) {
          this.$set(this.allChecked[shopIndex], itemIndex, value)
        },

        handleShopChecked({value, shopIndex}) {
          // let {allFalse, allTrue} = this.initAllChecked()
          // let result = value ? allTrue : allFalse
          let result = this.allChecked[shopIndex].map(v => value)
          this.$set(this.allChecked, shopIndex, result)
        },

        removeProduct(key, itemIndex, totalPrice) {
          // console.log(key, itemIndex)
          this.datasource[key].splice(itemIndex, 1)
          this.totalPrice -= totalPrice
        }

      },

      mounted() {
        fetch('/vue-basics/products.json')
          .then(response => response.json())
          .then(result => {
            this.datasource = result.data
            let {allFalse, allTrue} = this.initAllChecked()
            this.allChecked = allFalse
          })
      },

    })
  </script>
</body>
</html>